home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Mania 5
/
MacMania 5.toast
/
/
Tools&Utilities
/
BibTeX ƒ
/
BibTeXAlphaScripts.tcl
< prev
next >
Wrap
Text File
|
1996-11-19
|
13KB
|
421 lines
## -*-Tcl-*-
# ###################################################################
# BibTeX for MacOS -- scripts for GURL interaction with Alpha.
#
# FILE: "BibTeXAlphaScripts.tcl"
# created: 13/11/96 {1:05:50 am}
# last update: 19/11/96 {2:50:03 pm}
# Author: Vince Darley
# E-mail: <vince@das.harvard.edu>
# mail: Division of Applied Sciences, Harvard University
# Oxford Street, Cambridge MA 02138, USA
# www: <http://www.fas.harvard.edu/~darley/>
#
# INSTALLATION PROCEDURE:
#
# Add the following line to your "prefs.tcl" (a file located in Alpha's
# preferences folder inside your Preferences folder in your System folder):
#
# eventHandler GURL GURL GURLHandler
#
# This declares an event handler so we receive GURL events from
# the BibTeX application (Note: do not copy the '#' at the beginning of
# the line).
#
# Then move this file to the 'UserCode' folder inside the 'Tcl' folder
# which is located in the same place as the application Alpha. Now
# open Alpha, hit 'cmd-Y', and select 'Rebuild Tcl Indices' from the
# menu. After a minute or so, you can quit Alpha, and installation is
# complete.
#
# The only further choice you have is the value of the variable
# Bib_AutoIndex, which you can set below.
#
# modified by rev reason
# -------- --- --- -----------
# 13/11/96 VMD 1.0 original -- for use with BibTeX 1.1.4
# ###################################################################
##
# 0=never make index (except manually)
# 1=ask user when necessary
# 2=always remake when necessary
set Bib_AutoIndex 1
##
# -------------------------------------------------------------------------
#
# "GURLHandler" --
#
# Handle general GURL events by extracting the type 'ftp', 'http',…
# and calling a procedure ${type}GURLHandler with a single parameter
# which is the extracted resource. Can be put to more general use.
# -------------------------------------------------------------------------
##
proc GURLHandler {msg} {
if ![regsub {.*“(.*)”.*} $msg {\1} gurl] {
alertnote "Didn't understand GURL: $msg"
return
}
set GURLtype [lindex [split $gurl ":"] 0]
set GURLvalue [string range $gurl [expr 1+[string length $GURLtype]] end]
${GURLtype}GURLHandler $GURLvalue
}
##
# -------------------------------------------------------------------------
#
# "bibresultGURLHandler" --
#
# Handle 'bibresult' GURLs, as sent by the application BibTeX. These
# goto bibliography files, errors, warnings etc. We do the parsing here.
# See BibTeX's readme file for the syntax of the message.
# -------------------------------------------------------------------------
##
proc bibresultGURLHandler {msg} {
# Extract base .aux file name (full path description or 'Unknown')
set bpos [string first ".aux:" $msg]
set base_aux [string range $msg 0 [incr bpos 3]]
# Get rest of message
set msg [string range $msg [incr bpos 2] end]
if [regsub {.*: ([^.]+.(aux|bst|bib))} $msg {\1} filename] {
openTeXFile "$filename"
return
}
switch [lindex [split $msg "-"] 0] {
"Warning" {
# extract warning type and find the entry
# the last item is the entry (minus quotes possibly)
set msg [string range $msg 9 end]
set llen [llength $msg]
set item [string trim [lindex $msg [incr llen -1]] {"}]
set warning [lrange $msg 0 [incr llen -1]]
if { $warning == "I didn't find a database entry for" } {
# no entry exists, prompt to make one
set choice [prompt \
"No entry '$item' exists. What do you want to do?" \
"New entry" "Choices" \
"New entry" "New entry in new bibliography file" \
"Add .bib file to \\bibliography\{…\}" ]
switch $choice {
"New entry" {
# need to pick a .bib file
set bibfile [bibPickBibliography 1 \
"Select a bibliography file to which to add an entry"]
openTeXFile $bibfile
global entryNames
bibFormatSetup
newEntry [listpick -p "Which type of entry?" $entryNames]
insertText $item
nextTabStop
}
"New entry in new bibliography file" {
set bibfile [putfile "Save new bibliography as…" ".bib"]
if {$bibfile == ""} {
error "No bibliography file selected."
} else {
new -n $bibfile
}
global entryNames
bibFormatSetup
newEntry [listpick -p "Which type of entry?" $entryNames]
insertText $item
nextTabStop
}
"Add .bib file to \\bibliography\{…\}" {
# find .aux and open base .tex/.ltx
set base [lindex [split $base_aux "."] 0]
if [file exists ${base}.tex] {
set base ${base}.tex
} elseif [file exists ${base}.ltx] {
set base ${base}.ltx
} else {
error "Base file with name '${base}.xxx' not found."
}
openFileQuietly ${base}
# find bibliography, position cursor and add
endOfBuffer
if [catch {set pos [search -f 0 "\\bibliography\{" [getPos]]}] {
# add the environment
set pos [search -f 0 "\\end\{document\}" [getPos]]
goto [lindex $pos 0]
set preinsert "\\bibliography\{"
set postinsert "\}\r\r"
} else {
set preinsert ""
set postinsert ","
goto [lindex $pos 1]
}
set bibfile [bibPickBibliography 0 \
"Select a bibliography file to add"]
insertText "${preinsert}[lindex [split $bibfile "."] 0]${postinsert}"
}
"Cancel" {
# nothing
}
}
return
} else {
# go to a current entry
bibGotoEntry $item
beep
message "Warning--$warning $item"
return
}
}
default {
bib_GotoError $msg
}
}
}
##
# -------------------------------------------------------------------------
#
# "bib_GotoError" --
#
# Parse and goto a specific error in a particular file. Look locally for
# the correct text in case we've edited the file.
# -------------------------------------------------------------------------
##
proc bib_GotoError {msg} {
# it's an error. Extract type, line, filename, and position of error
set errtype [lindex [split $msg "-"] 0]
if ![regsub {.*line ([0-9]+) .*} $msg {\1} line] {
error "Failed to parse line number from BibTeX error"
}
if ![regsub {.*of file (.*) a .*} $msg {\1} filename] {
error "Failed to parse filename from BibTeX error"
}
if ![regsub {.*a '(.*)' at.*} $msg {\1} problem] {
error "Failed to parse filename from BibTeX error"
}
if ![regsub {.*at (.*)} $msg {\1} linepos] {
error "Failed to parse line position from BibTeX error"
}
openTeXFile $filename
goto [rowColToPos $line $linepos]
# Un-map the encoding we did on the other end.
regsub "‘" $problem "\{" problem
regsub "’" $problem "\}" problem
# Un-map the encoding we did on the other end.
regsub "‘" $errtype "\{" errtype
regsub "’" $errtype "\}" errtype
set pos [getPos]
set t [getText [lineStart $pos] $pos]
if {$t != $problem} {
# we've edited the file; look locally
set pr "^[quoteExpr2 $problem]"
if {![catch {search -f 0 -r 1 -l [expr $pos - 300] $pr $pos} found]} {
set pos [lindex $found 1]
} elseif {![catch {search -f 1 -r 1 -l [expr $pos + 300] $pr $pos} found]} {
set pos [lindex $found 1]
}
}
select [lineStart $pos] $pos
beep
message "$errtype"
return
}
##
# -------------------------------------------------------------------------
#
# "TeXEnsureSearchPathSet" --
#
# Make sure TeX mode has built our search path, so we can find
# bibliography files. Perhaps we should have our own variable
# for these?
# -------------------------------------------------------------------------
##
proc TeXEnsureSearchPathSet {} {
global TeXSearchPath
if { [llength $TeXSearchPath] == 0 } {
message "building TeX search path…"
set TeXSearchPath [buildTeXSearchPath]
message ""
}
}
##
# -------------------------------------------------------------------------
#
# "bibPickBibliography" --
#
# Put up a list-dialog so the user can select a bibliography file for
# some action (taken by the caller). Can also create a new file if
# desired.
# -------------------------------------------------------------------------
##
proc bibPickBibliography {{allowNew 1} {prompt "Pick a bibliography file"}} {
set biblist [bibListAllBibliographies]
if $allowNew {
lappend biblist {New file…}
}
set bibfile [listpick -p $prompt $biblist]
if {$bibfile == ""} {
error "No bibliography file selected."
} elseif {$bibfile == "New file…" } {
set bibfile [putfile "Save new bibliography as…" ".bib"]
if {$bibfile == ""} {
error "No bibliography file selected."
} else {
set fout [open $bibfile w]
close $fout
}
}
return [file tail $bibfile]
}
##
# -------------------------------------------------------------------------
#
# "bibListAllBibliographies" --
#
# Return all bibliographies on the search path.
# -------------------------------------------------------------------------
##
proc bibListAllBibliographies {} {
TeXEnsureSearchPathSet
global TeXSearchPath
foreach f $TeXSearchPath {
eval lappend biblist [glob -nocomplain ${f}*.bib]
}
return $biblist
}
##
# -------------------------------------------------------------------------
#
# "bibGotoEntry" --
#
# Look for a bib entry in the given list of files, or if that fails or
# isn't given, look in all available bib files on the search path.
# -------------------------------------------------------------------------
##
proc bibGotoEntry {entry {biblist {}}} {
if ![catch {bib_GotoEntryFromIndex $entry}] {
return
}
if {[llength $biblist] && ![catch {bib_GotoEntry $entry $biblist}]} {
return
}
if ![catch {bib_GotoEntry $entry [bibListAllBibliographies]}] {
return
}
beep
error "Can't find entry '$entry' in the .bib file(s)"
}
##
# -------------------------------------------------------------------------
#
# "bib_GotoEntryFromIndex" --
#
# Look in the bibIndex and find an entry very quickly.
# -------------------------------------------------------------------------
##
proc bib_GotoEntryFromIndex {entry} {
set bibTopPat {@([a-zA-Z]+)[\{\(][ ]*}
global PREFS
# if it fails, but we succeed later, we will have the opportunity
# to rebuild the bibIndex
if [file exists "${PREFS}:bibIndex"] {
source "${PREFS}:bibIndex"
global bibIndex
foreach f [array names bibIndex] {
if [regexp "\[ \r\n\]$entry\[ \r\n\]" "$bibIndex($f)"] {
openFileQuietly $f
set p [search -f 1 -r 1 $bibTopPat$entry 0]
eval select $p
centerRedraw
eval select $p
unset bibIndex
return
}
}
unset bibIndex
}
error "Entry '$entry' not found in bibIndex"
}
##
# -------------------------------------------------------------------------
#
# "bib_GotoEntry" --
#
# Find a bib entry in one of the given list of files, and signal an
# error if the entry isn't found. I think this is the quickest way.
# -------------------------------------------------------------------------
##
proc bib_GotoEntry {entry biblist} {
set bibTopPat {@([a-zA-Z]+)[\{\(][ ]*}
set cid [scancontext create]
scanmatch $cid $bibTopPat$entry {
set found "$matchInfo(subindex0)"
}
set found ""
foreach f $biblist {
message "Searching [file tail $f]…"
if {![catch {set fid [open $f]}]} {
scanfile $cid $fid
close $fid
if {$found != ""} {
openFileQuietly $f
eval select $found
scancontext delete $cid
global bib_AutoIndex
# make the index since it was obviously out of date
if {$Bib_AutoIndex == 2 || [askyesno "The bibIndex is obviously out of date. Rebuild?"]=="yes"} {
bib_MakeIndex
}
return
}
}
}
scancontext delete $cid
error "Entry '$entry' not found."
}
##
# -------------------------------------------------------------------------
#
# "bib_MakeIndex" --
#
# Build the bibIndex file which allows for very fast lookup of bib
# entries.
# -------------------------------------------------------------------------
##
proc bib_MakeIndex {} {
global PREFS
set bibTopPat2 {^[ ]*@([a-zA-Z]+)[\{\(][ ]*([^=, ]+)}
set cid [scancontext create]
# this will actually mark strings as well
scanmatch $cid $bibTopPat2 {
if {[string tolower $matchInfo(submatch0)] != "string"} {
lappend found $matchInfo(submatch1)
}
}
set bout [open "${PREFS}:bibIndex" w]
puts $bout "# Bibliography index file for quick reference lookup"
puts $bout "# Created on [mtime [now]]"
foreach f [bibListAllBibliographies] {
set found {}
puts $bout "set \"bibIndex($f)\" \{"
message "Scanning [file tail $f]…"
if {![catch {set fid [open $f]}]} {
scanfile $cid $fid
close $fid
}
puts $bout $found
puts $bout "\}"
}
close $bout
scancontext delete $cid
message "bibIndex creation complete"
}